package milkyway.hightech.banking;

import milkyway.hightech.conditions.InvAccountCond;
import milkyway.hightech.exceptions.AccountNotExpiredException;
import milkyway.hightech.exceptions.AmountLessThanZeroException;
import milkyway.hightech.exceptions.NotEnoughMoneyException;
import milkyway.hightech.money.Currency;
import milkyway.hightech.money.Money;
import milkyway.hightech.timer.TimeEmitter;

import java.math.BigDecimal;
import java.math.BigInteger;

import java.util.Calendar;
import java.util.Observable;

/**
 *
 * @author michael
 */
public class InvestmentAccount extends Account
{
    private InvAccountCond cond;
    private int period;

    /**
     *
     * @param accountNumber
     * @param accountHolder
     * @param currency
     * @param conditions
     * @param calendar
     */
    public InvestmentAccount(int accountNumber, String accountHolder,
        Currency currency, InvAccountCond conditions, Calendar calendar)
    {
        super(accountNumber, accountHolder, currency, calendar);
        this.cond = conditions;
        this.period = conditions.getContractPeriod() * 30;
    }

    /**
     *
     * @param o
     * @param obj
     */
    @Override
    public void update(Observable o, Object obj)
    {
        setChanged();
        period--;

        if (period == 0)
        {
            notifyObservers(this);
        }
    }

    // interfaces

    /**
     *
     * @return
     */
    public InvAccountCond getAccountConditions()
    {
        return cond;
    }

    public void renewContract()
    {
        this.calendar = TimeEmitter.getInstance().getCalendar();
        period = cond.getContractPeriod() * 30;
    }

    /**
     * pays the current interest on credit.
     */
    @Override
    public void payInterest()
    {
        BigDecimal d = new BigDecimal(getAccountBalance());
        d = d.divide(new BigDecimal("100"));

        BigDecimal interest = BigDecimal.valueOf(cond.getCreditInterest());
        d = d.multiply(interest);
        Money m = new Money(d.toBigInteger(), money.getCurrency());
        this.enterOnCredit(m, "pay interest");

        if (getAccountBalance().compareTo(new BigInteger("0")) == 1)
        {
            renewContract();
        }
    }

    /**
     *
     * @param amount
     * @param reasonOfTransfer
     */
    @Override
    public void enterOnCredit(Money amount, String reasonOfTransfer)
    {
        if (amount.getValue().signum() <= 0)
        {
            throw new AmountLessThanZeroException();
        }
        
        else if ((period > 0) && (period < cond.getContractPeriod() * 30))
        {
            throw new AccountNotExpiredException();
        }
        
        else
        {
            update(1, amount, reasonOfTransfer);
        }
    }

    /**
     *
     * @param amount
     * @param reasonOfTransfer
     */
    @Override
    public void enterOnDebit(Money amount, String reasonOfTransfer)
    {
        BigInteger b = getAccountBalance();
        int i = amount.getValue().compareTo(b);

        if (amount.getValue().signum() == -1)
        {
            throw new AmountLessThanZeroException();
        }
        
        else if ((period > 0) && (period < cond.getContractPeriod() * 30))
        {
            throw new AccountNotExpiredException();
        }
        
        else if (i == 1)
        {
            throw new NotEnoughMoneyException();
        }
        
        else
        {
            update(-1, amount, reasonOfTransfer);
        }
    }
}